﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Text;
using System.Collections.Generic;
using Silverlight.ControlToolkit.Windows;

namespace Silverlight.ControlToolkit.Windows
{
    [TemplatePart(Name = BusyBox.RootElement, Type = typeof(FrameworkElement))]
    [TemplatePart(Name = BusyBox.MessageBorderElement, Type = typeof(FrameworkElement))]
    [TemplatePart(Name = BusyBox.MessageTextElement, Type = typeof(TextBlock))]
    [TemplatePart(Name = BusyBox.ParentCanvasElement, Type = typeof(Panel))]
    [TemplatePart(Name = BusyBox.ChildCanvasElement, Type = typeof(Panel))]
    [TemplatePart(Name = BusyBox.SpinningAnimationStoryboard, Type = typeof(Storyboard))]
    public class BusyBox : Control
    {

        private const string RootElement = "RootElement";
        private const string MessageBorderElement = "MessageBorderElement";
        private const string MessageTextElement = "MessageTextElement";
        private const string ParentCanvasElement = "ParentCanvasElement";
        private const string ChildCanvasElement = "ChildCanvasElement";
        private const string SpinningAnimationStoryboard = "SpinningAnimationStoryboard";

        private FrameworkElement _rootElement;
        private FrameworkElement _messageBorderElement;
        private TextBlock _messageTextElement;
        private Panel _parentCanvasElement;
        private Panel _childCanvasElement;
        private Storyboard _spinningAnimationStoryboard;
        private Brush _spinnerColor = new SolidColorBrush(Colors.Green); //Default - green

        public static List<BusyBox> AllOpenInstances = new List<BusyBox>();

        //This class cannot be created at design time.  It should be invoked at run-time only
        public BusyBox()
            : base()
        {
            this.DefaultStyleKey = typeof(BusyBox);
        }

        public static Style DefaultStyle { get; set; }

        public static ControlTemplate DefaultTemplate { get; set; }

        public static string DefaultStyleXaml
        {
            set
            {
                DefaultStyle = System.Windows.Markup.XamlReader.Load(value) as Style;
            }

        }

        public static string DefaultTemplateXaml
        {
            set
            {
                DefaultTemplate = System.Windows.Markup.XamlReader.Load(value) as ControlTemplate;
            }

        }


        public static readonly DependencyProperty SpinnerColorProperty =
            DependencyProperty.Register("SpinnerColor", typeof(Brush), typeof(BusyBox),
                                new PropertyMetadata(new PropertyChangedCallback(SpinnerColorChangedCallback)));

        private static void SpinnerColorChangedCallback(DependencyObject obj,
                                DependencyPropertyChangedEventArgs args)
        {
            if (obj != null)
                ((BusyBox)obj)._spinnerColor =  args.NewValue as Brush;
        }

        public Brush SpinnerColor
        {
            get
            {
                return (Brush)GetValue(SpinnerColorProperty);
            }

            set
            {
                SetValue(SpinnerColorProperty, value);
            }
        }

        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();

            _rootElement = (FrameworkElement)GetTemplateChild(BusyBox.RootElement);
            _messageBorderElement = (FrameworkElement)GetTemplateChild(BusyBox.MessageBorderElement);
            _messageTextElement = (TextBlock)GetTemplateChild(BusyBox.MessageTextElement);
            _parentCanvasElement = (Panel)GetTemplateChild(BusyBox.ParentCanvasElement);
            _childCanvasElement = (Panel)GetTemplateChild(BusyBox.ChildCanvasElement);
            _spinningAnimationStoryboard = (Storyboard)GetTemplateChild(BusyBox.SpinningAnimationStoryboard);
        }



        /// <summary>
        /// Shows the specified message.
        /// </summary>
        /// <param name="message">The message.</param>
        /// <param name="owner">The control on which to popup this message.  The popup will be modal only within its owner</param>
        /// <returns></returns>
        public static BusyBox Show(string message, FrameworkElement owner)
        {
            BusyBox objBusyBox = new BusyBox();
            objBusyBox.ApplyDefaultStyleTemplate(DefaultStyle, DefaultTemplate);
            
            //Append a space at the end so that the complext text is visible
            //This issue got introduced in 2.0 release version. For some reasons it truncates the last word if it 
            //does not have any space next to it
             objBusyBox._messageTextElement.Text = message + " ";


             objBusyBox.ShowDialog(owner).DialogBoxClosed += new DialogBoxClosedEventHandler(BusyBox_DialogBoxClosed);

            AllOpenInstances.Add(objBusyBox);

            objBusyBox.drawCanvas();
            objBusyBox._spinningAnimationStoryboard.Begin();
             
            return objBusyBox;
        }

        static void BusyBox_DialogBoxClosed(object sender, DialogBoxEventArgs e)
        {
            if (sender is ModalDialog)
            {
                AllOpenInstances.Remove(((ModalDialog)sender).Child as BusyBox);
            }
        }

        /// <summary>
        /// Shows the specified message.
        /// </summary>
        /// <param name="message">The message.</param>
        /// <returns></returns>
        public static BusyBox Show(string message)
        {
            return BusyBox.Show(message, null);
        }

        private void drawCanvas()
        {
            for (int i = 0; i < 12; i++)
            {
                Line line = new Line()
                {
                    X1 = 15,
                    X2 = 15,
                    Y1 = 0,
                    Y2 = 6,
                    StrokeThickness = 5,
                    Stroke = _spinnerColor, // new SolidColorBrush(Colors.Green), // Color.FromArgb(255, 225, 225, 225)), 
                    Width = 30,
                    Height = 30,
                    VerticalAlignment = VerticalAlignment.Center,
                    HorizontalAlignment = HorizontalAlignment.Center,
                    RenderTransformOrigin = new Point(.5, .5),
                    RenderTransform = new RotateTransform() { Angle = i * 30 },
                    Opacity = (double)i / 12
                };

                _childCanvasElement.Children.Add(line);
            }
        } 


    }
}
